/*********************************************************
          File Name:pisces_event.c
          Author: Abby Cin
          Mail: abbytsing@gmail.com
          Created Time: Sat 25 Apr 2015 11:09:22 AM CST
**********************************************************/

#include "global.h"
#include "pisces_log.h"
#include "pisces_event.h"
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <ev.h>

extern int pisces_unblock_socket(int);
extern void transfer_data(int);
extern void pisces_err(int, int);

static void connect_cb(struct ev_loop *loop, ev_io *w, int rev)
{
        int connfd;
        int res;

        connfd = accept(w->fd, NULL, NULL);
        if(connfd == -1)
        {
                if(errno == EAGAIN || errno == EWOULDBLOCK)
                        pisces_log(P_LOG_IFO, "no incoming connection!");
                else if(errno != EINTR)
                        pisces_log(P_LOG_ERR, "accept %s", strerror(errno));
        }

        res = pisces_unblock_socket(connfd);
        if(res == -1)
                pisces_log(P_LOG_ERR, "failed to mark socket unblock %s", strerror(errno));
        switch(fork())
        {
                case -1:
                        if(errno == EAGAIN)
                                pisces_err(connfd, 503);
                        else
                        {
                                pisces_log(P_LOG_ERR, "%s fork() %s", __FILE__, strerror(errno));
                                exit(1);
                        }
                        break;
                case 0:
                        transfer_data(connfd);
                        exit(0);
                default:
                        close(connfd);
                        break;
        }
}

void pisces_event_loop(pisces_ctx_t *ctx)
{
        struct ev_loop *loop = ev_loop_new(EVBACKEND_EPOLL);
        ev_io sio;

        ev_io_init(&sio, connect_cb, ctx->listenfd, EV_READ);
        ev_io_start(loop, &sio);
        ev_run(loop, 0);
}
